package Core

import spinal.core._

object LoongArch {
    def rdRange = 4 downto 0
    def rjRange = 9 downto 5
    def rkRange = 14 downto 10
    def raRange = 19 downto 15
    def csrAddr = 23 downto 10
    //def imm8Range = 17 downto 10

    //def OP_SHIFT =

    case class IMMALL(instruction : Bits) extends Area {
        def imm5 = instruction(14 downto 10)
        //def imm8 = instruction(17 downto 10);
        def imm12 = instruction(21 downto 10)
        def imm16 = instruction(25 downto 10)
        def imm21 = instruction(4 downto 0) ## instruction(25 downto 10)
        def imm26 = instruction(9 downto 0) ## instruction(25 downto 10)
        def imm14 = instruction(23 downto 10)

        def imm12_unsigned_op : Bool = instruction.mux(
            ANDI -> True,
            ORI -> True,
            XORI -> True,
            default -> False
        )

        def imm12_signed_op : Bool = instruction.mux(
            SLTI -> True,
            SLTUI -> True,
            ADDI -> True,
            LD_B -> True,
            LD_H -> True,
            LD_W -> True,
            ST_B -> True,
            ST_H -> True,
            ST_W -> True,
            LD_BU -> True,
            LD_HU -> True,
            default -> False
        )

        def imm14_op : Bool = instruction.mux(
            LL -> True,
            SC -> True,
            default -> False
        )

        def imm5_op : Bool = instruction.mux(
            SLLI -> True,
            SRLI -> True,
            SRAI -> True,
            default -> False
        )

        def imm16_op : Bool = instruction.mux(
            JIRL -> True,
            BEQ -> True,
            BNE -> True,
            BLT -> True,
            BGE -> True,
            BLTU -> True,
            BGEU -> True,
            default -> False
        )

        def imm_lui_or_pcaddu_op : Bool = instruction.mux(
            LUI -> True,
            default -> False
        )

        def imm26_op : Bool = instruction.mux(
            BRANCH_B -> True,
            BL -> True,
            default -> False
        )

        def imm14_sext = B((17 downto 0) -> imm14(13)) ## imm14
        def imm12_sext = B((19 downto 0) -> imm12(11)) ## imm12
        def imm12_usext = B(((19) downto 0) -> False) ## imm12
        def imm5_usext = B((26 downto 0) -> False) ## imm5
        def imm16_sext = B((15 downto 0) -> imm16(15)) ## imm16
        def imm_lui_or_pcaddu = instruction(24 downto 5) ## B(0, 12 bits)
        def imm26_sext = imm26 ## B(0, 6 bits)

        /**


        def imm12_signed_op : Bool = instruction.mux(
            SLTI -> True,
            SLTUI -> True,
            ADDI -> True,
            LD_B -> True,
            LD_H -> True,
            LD_W -> True,
            ST_B -> True,
            ST_H -> True,
            ST_W -> True,
            LD_BU -> True,
            LD_HU -> True,
            default -> False
        )

        def imm12_unsigned_op : Bool = instruction.mux(
            ANDI -> True,
            ORI -> True,
            XORI -> True,
            default -> False
        )

        def imm16_op : Bool = instruction.mux(
            JIRL -> True,
            BEQ -> True,
            BNE -> True,
            BLT -> True,
            BGE -> True,
            BLTU -> True,
            BGEU -> True,
            default -> False
        )

        def imm26_op : Bool = instruction.mux(
            BRANCH_B -> True,
            BL -> True,
            default -> False
        )

        def NOTWRITE = instruction.mux(
            ST_B -> True,
            ST_H -> True,
            ST_W -> True,
            BEQ -> True,
            BNE -> True,
            BLT -> True,
            BGE -> True,
            BLTU -> True,
            BGEU -> True,
            BRANCH_B -> True
        )

        def imm5_usext = B((26 downto 0) -> 0) ## imm5
        def imm12_sext = B((19 downto 0) -> imm12(11)) ## imm12
        def imm12_usext = B((19 downto 0) -> 0) ## imm12
        def imm16_sext = B((15 downto 0) -> imm16(15)) ## imm16
        def imm26_sext = B((25 downto 0) -> imm26(25)) ## imm26*/

    }

    def LUI  = M"0001010-------------------------"
    def ADD  = M"00000000000100000---------------"
    def SUB  = M"00000000000100010---------------"
    def SLT  = M"00000000000100100---------------"
    def SLTU = M"00000000000100101---------------"
    def NOR  = M"00000000000101000---------------"
    def AND  = M"00000000000101001---------------"
    def OR   = M"00000000000101010---------------"
    def XOR  = M"00000000000101011---------------"
    def SLL  = M"00000000000101110---------------"
    def SRL  = M"00000000000101111---------------"
    def SRA  = M"00000000000110000---------------"
    def MUL  = M"00000000000111000---------------"

    def MULH  = M"00000000000111001---------------"
    def MULHU = M"00000000000111010---------------"
    def DIV   = M"00000000001000000---------------"
    def MOD   = M"00000000001000001---------------"
    def DIVU  = M"00000000001000010---------------"
    def MODU  = M"00000000001000011---------------"

    def BREAK   = M"00000000001010100---------------"
    def SYSCALL = M"00000000001010110---------------"

    def SLLI  = M"00000000010000001---------------"
    def SRLI  = M"00000000010001001---------------"
    def SRAI  = M"00000000010010001---------------"

    def SLTI  = M"0000001000----------------------"
    def SLTUI = M"0000001001----------------------"
    def ADDI  = M"0000001010----------------------"
    def ANDI  = M"0000001101----------------------"
    def ORI   = M"0000001110----------------------"
    def XORI  = M"0000001111----------------------"

    def LD_B  = M"0010100000----------------------"
    def LD_H  = M"0010100001----------------------"
    def LD_W  = M"0010100010----------------------"
    def LL    = M"00100000------------------------"
    def ST_B  = M"0010100100----------------------"
    def ST_H  = M"0010100101----------------------"
    def ST_W  = M"0010100110----------------------"
    def SC    = M"00100001------------------------"

    def LD_BU = M"0010101000----------------------"
    def LD_HU = M"0010101001----------------------"

    def JIRL  = M"010011--------------------------"
    def BRANCH_B     = M"010100--------------------------"
    def BL    = M"010101--------------------------"
    def BEQ   = M"010110--------------------------"
    def BNE   = M"010111--------------------------"
    def BLT   = M"011000--------------------------"
    def BGE   = M"011001--------------------------"
    def BLTU  = M"011010--------------------------"
    def BGEU  = M"011011--------------------------"
    def PCADDU = M"0001110-------------------------"
    def CSRRD = M"00000100------------------------"
    def CSRWR = M"00000100------------------------"
    def CSRXCHG = M"00000100------------------------"
    def ERTN  = M"0000011001001000001110----------"

    object CSR {
        def CRMD  = 0x0
        def PRMD  = 0x1
        def ESTAT = 0x5
        def ERA   = 0x6
        def EENTRY = 0xc
        def SAVE0 = 0x30
        def SAVE1 = 0x31
        def SAVE2 = 0x32
        def SAVE3 = 0x33

        //CRMD
        def PLV = 1 downto 0
        def IE = 2
        def DA = 3
        def PG = 4
        def DATF = 6 downto 5
        def DATM = 8 downto 7
        def WE = 9

        //PRMD
        def PPLV = 1 downto 0
        def PIE = 2
        def PWE = 3

        //ESTAT
        def IS_1 = 1 downto 0 //IS[1:0]
        def IS_2 = 12 downto 2 //IS[12:2]
        def ECODE = 21 downto 16
        def ESUBCODE = 30 downto 22

        object ECODE_NAME {
            def INT = 0x0
            def PIL = 0x1
            def PIS = 0x2
            def PIF = 0x3
            def PME = 0x4
            def PNR = 0x5
            def PNX = 0x6
            def PPI = 0x7
            def ADEF = 0x8
            def ADEM = 0x8
            def ALE = 0x9
            def BCE = 0xA
            def SYS = 0xB
            def BRK = 0xC
            def INE = 0xD
            def IPE = 0xE
            def FPD = 0xF
            def SXD = 0x10
            def ASXD = 0x11
            def FPE = 0x12
            def VFPE = 0x12
            def WPEF = 0x13
            def WPEM = 0x13
            def BTD = 0x14
            def BTE = 0x15
            def GSPR = 0x16
            def HVC = 0x17
            def GCSC = 0x18
            def GCHC = 0x18
        }

        //ERA
        def PC = 31 downto 0

        //EENTRY
        def VPN = 31 downto 12

        //SAVE
        def DATA = 31 downto 0

    }
}


